package com.qianfeng.iot.group.service.impl;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import cn.hutool.core.lang.UUID;
import com.dc3.common.bean.R;
import com.dc3.common.exception.AddException;
import com.dc3.common.model.Group;
import com.qianfeng.iot.group.service.GroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;

/**
 * Created by Jackiechan on 2022/8/5 20:25
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Service
@Transactional
public class GroupServiceImpl implements GroupService {

    private R2dbcEntityTemplate r2dbcEntityTemplate;

    @Autowired
    public void setR2dbcEntityTemplate(R2dbcEntityTemplate r2dbcEntityTemplate) {
        this.r2dbcEntityTemplate = r2dbcEntityTemplate;
    }

    @Override
    public Mono<R<Object>> addGroup(Group group) {
        //我们要先检查数据是不是ok的
        //检查当前分组是不是已经存在
        //如果存在就判断下当前的状态是不是删除
        //如果不是删除就提示已经存在, 如果是删除的,就更新为存在,并且更新时间
        return findByName(group.getName(), group.getTenantId())//将数据转换为我们从数据查询的数据,进行校验使用的
                .defaultIfEmpty(group)//空的使用原始数据
                //进行相关的判断,比如判断数据是不是已经被删除,如果是就更新,如果不是就报错
                .flatMap(group1 -> {
                    //就是查询到的数据是没有id的,没有id其实就是说上面没有查询到数据,就是没有数据
                    if (!StringUtils.hasText(group1.getId())) {
                        group1.setId(UUID.randomUUID().toString(true));
                        //如果是0或者null,就是说没有删除数据,但是可能是没有数据
                        return r2dbcEntityTemplate.insert(Group.class).into("dc3_group").using(group);
                    } else if (group1.getDeleted() == 1) {
                        //数据存在,但是被删除了,重新改回启用
                        group1.setDeleted(0);
                        group1.setUpdateTime(LocalDateTime.now());
                        return updateGroup(group1);
                    }
                    throw new AddException("分组%s已经存在", group1.getName());
                })//当前的group就是从数据库中查询到的数据,如果上面没数据,这个操作不会执行
                .map(result -> R.ok())
                .doOnError(Throwable::printStackTrace)
                .onErrorReturn(R.fail("添加失败"));
              //如果上面没有查询到数据,应该执行添加操作


    }

    /**
     * 更新,实际上更新也是需要租户id
     * @param group
     * @return
     */
    @Override
    public Mono<Integer> updateGroup(Group group) {
        return r2dbcEntityTemplate.update(Group.class).inTable("dc3_group")
                //租户只能更新自己下面的分组
                .matching(Query.query(Criteria.where("id").is(group.getId()).and(Criteria.where("tenant_id").is(group.getTenantId()))))
                .apply(
                        Update.update("update_time",group.getUpdateTime())
                                .set("deleted",group.getDeleted())
                                .set("name",group.getName())
                                .set("description",group.getDeleted()));
    }

    /**
     * 删除数据,其实只能删除租户下面的这些id对应的数据
     * @param ids
     * @return
     */
    @Override
    public Mono<Integer> deleteGroupByIds(List<String> ids,String tenantId) {
      return   r2dbcEntityTemplate.update(Group.class).inTable("dc3_group")
                //租户只能更新自己下面的分组
                .matching(Query.query(Criteria.where("id").in(ids).and(Criteria.where("tenant_id").is(tenantId))))
                .apply(
                        Update.update("deleted",1));
    }

    @Override
    public Mono<Group> findById(String id,String tenantId) {
        return r2dbcEntityTemplate.select(Group.class).from("dc3_group").matching(Query.query(Criteria.where("id").is(id)
                .and(Criteria.where("tenant_id").is(tenantId)))).first();
    }

    @Override
    public Mono<Group> findByName(String groupName,String tenantId) {
        return r2dbcEntityTemplate.select(Group.class).from("dc3_group").matching(Query.query(Criteria.where("name").is(groupName)
                .and(Criteria.where("tenant_id").is(tenantId)))).first();
    }

    @Override
    public Flux<Group> findAll(String tenantId) {
        return r2dbcEntityTemplate.select(Group.class).from("dc3_group").matching(Query.query(Criteria.where("tenant_id").is(tenantId))).all();
    }
}
